home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / PlainTalk / Speech Recognition / Sample Code / Tiny SR Example / CodeWarrior Tiny Example / TinySRApp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-10  |  10.0 KB  |  375 lines  |  [TEXT/MPS ]

  1. /************************************************************
  2.  
  3. Created: Wednesday, May 4, 1994 at 1:50:15 PM
  4.     TinySRApp.c
  5.     
  6.     Simple Speech Recognition Toolbox Sample Application
  7.  
  8.         Copyright Apple Computer, Inc.    1994
  9.         All rights reserved
  10.  
  11. ************************************************************/
  12.  
  13.  
  14. #include "SpeechRecognition.h"
  15. #include <GestaltEqu.h>
  16. #include <Quickdraw.h>
  17. #include <Dialogs.h>
  18. #include <Fonts.h>
  19. #include <AppleEvents.h>
  20. #include <string.h>
  21. #include <Menus.h>
  22.  
  23. /*****************************************************************************/
  24.  
  25. /* Prototypes and globals */
  26.  
  27. OSErr    InitStuff (void);
  28. OSErr    InitAndStartSpeechRecognition (void);
  29. void    MainLoop (void);
  30. void    CleanupStuff (void);
  31. void    CleanupSpeechRecognitionStuff (void);
  32. OSErr    MakeALanguageModel (LanguageModel *lm);
  33. pascal OSErr HandleSpeechDoneAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon);
  34. void    DisplayString (Str255 str);
  35.  
  36. DialogPtr             gDialog;
  37. RecognitionSystem    gSystem;
  38. Recognizer            gRecognizer;
  39. LanguageModel        gModel;
  40. Boolean                gFinished;
  41.  
  42. /*****************************************************************************/
  43.  
  44. void main ()
  45. {
  46.     OSErr status = InitStuff ();
  47.     if (!status) {
  48.         MainLoop ();
  49.         CleanupStuff ();
  50.     }
  51. }
  52.  
  53. /*****************************************************************************/
  54.  
  55. /* main is the entry point to his program.    */
  56.  
  57. OSErr InitStuff ()
  58. {
  59.     OSErr                status = noErr;
  60.     Rect                rBounds;
  61.     GrafPtr                oldPort;
  62.     LMFlags                autoFin = kNoFinishing;
  63.     MenuHandle            menuH;
  64.     
  65.         /* Adjust heap */
  66.     MaxApplZone();
  67.     MoreMasters();
  68.     MoreMasters();
  69.     
  70.         /* Init toolboxes */
  71.     InitGraf(&qd.thePort);
  72.     InitFonts();
  73.     FlushEvents(everyEvent,0);
  74.     InitWindows();
  75.     InitMenus();
  76.     TEInit();
  77.     InitDialogs(0);
  78.     InitCursor();
  79.  
  80.     menuH = NewMenu (1,"\pSR Test");
  81.     if (menuH) InsertMenu (menuH, 0);
  82.     AddResMenu(menuH,'DRVR');
  83.     DrawMenuBar();
  84.  
  85.  
  86.         /* Make a dialog in which we'll display results */
  87.     SetRect (&rBounds, 50,50,450,150);
  88.     gDialog = NewDialog(NULL,&rBounds,"\p",true,dBoxProc,(WindowPtr)-1,false,0,NULL);
  89.     if (!gDialog)
  90.         status = -1;
  91.     else {
  92.         GetPort (&oldPort);
  93.         SetPort (gDialog);
  94.         MoveTo (10,80);
  95.         TextSize (9);
  96.         DrawString ("\p(Say 'Hi', 'Goodbye', 'What time is it', or 'What day is it'.  Click here to exit.)");
  97.         SetPort (oldPort);
  98.     }
  99.     
  100.     
  101.     if (!status)
  102.         status = InitAndStartSpeechRecognition ();
  103.     
  104.     if (!status)
  105.         gFinished = false;
  106.     else
  107.         gFinished = true;
  108.         
  109.     return status;
  110. }
  111.  
  112. /*****************************************************************************/
  113.  
  114. /* This routine initializes speech recognition, installs an AppleEvent handler
  115.     to handle result notifications from the Speech Recognition Toolbox, calls
  116.     another routine to build a simple language model (which specifies a few
  117.     phrases a user can say), makes that language model active by calling
  118.     SRSetLanguageModel, and starts the recognizer listening.  A more realistic
  119.     application would have more complicated language models (perhaps having
  120.     different language models for different contexts -- using SRSetLanguageModel
  121.     to make the appropriate one active), or would use the language model
  122.     manipulation routines in the Speech Recognition Toolbox to change the
  123.     active language model as the program was used to reflect what the user
  124.     might say in any given situation.
  125. */
  126.  
  127. OSErr InitAndStartSpeechRecognition ()
  128. {
  129.     OSErr    status;
  130.     long    attributes;
  131.     
  132.     /* The SROpenRecognitionSystem loads lots of data and can take a few
  133.         seconds, so display a message indicating this may take a moment.
  134.         This would be a good place to show the watch cursor as well. */
  135.     DisplayString ("\pStarting up...");
  136.  
  137.         /* Make sure SpeechRecognition Toolbox is available */
  138.     status = Gestalt (gestaltSpeechRecognitionVersion, &attributes);
  139.         /* Version number must be at least 1.2.1 to support Speech Recognition Toolbox API
  140.             documented here. */
  141.     if (!status)
  142.         if (attributes < 0x00000121)
  143.             status = -1;
  144.  
  145.         /* Open a RecognitionSystem */
  146.     if (!status)
  147.         status = SROpenRecognitionSystem (&gSystem, kDefaultRecognitionSystemID);
  148.  
  149.         /* Create a recognizer with default speech source -- e.g. the desktop microphone */
  150.     if (!status)
  151.         status = SRNewRecognizer (gSystem, &gRecognizer, kSRDefaultSpeechSource);
  152.                 
  153.         
  154.         /* Install an AppleEvent handler so recognizer can send us recognition results.
  155.             We could alternatively use a callback routine.  That's described elsewhere. */
  156.     if (!status)
  157.         status = AEInstallEventHandler(kAESpeechSuite, kAESpeechDone,
  158.                 (AEEventHandlerUPP) HandleSpeechDoneAppleEvent, 0, false);
  159.                             
  160.             
  161.         /* For this example, we will just make one language model,
  162.             make it active, and start listening. */
  163.  
  164.         /* Make a simple language model (LM) */
  165.     if (!status)
  166.         status = MakeALanguageModel (&gModel);
  167.  
  168.         /* Use this LM in recognition */
  169.     if (!status)
  170.         status = SRSetLanguageModel (gRecognizer, gModel);
  171.  
  172.         /* Release our reference to the LM now, since we don't need it any more.
  173.             The recognizer keeps it's own reference to the LM until we release the 
  174.             recognizer. */
  175.     if (!status)
  176.         status = SRReleaseObject (gModel);
  177.  
  178.  
  179.         /* Have the recognizer start processing sound */
  180.     if (!status)
  181.         status = SRStartListening (gRecognizer);
  182.  
  183.     if (!status)
  184.         DisplayString ("\pReady");
  185.     else
  186.         DisplayString ("\pBummer");
  187.  
  188.     return status;
  189. }
  190.  
  191.  
  192. /*****************************************************************************/
  193.  
  194. void MainLoop ()
  195. {
  196.     Boolean         gotEvent;
  197.     EventRecord        event;
  198.     DialogPtr        theDialog;
  199.     short            itemHit;
  200.     Point            pt;
  201.     GrafPtr            oldPort;
  202.     
  203.         /* Here's our overly-simple main event loop */
  204.         /*    We quit if mouse is clicked in window,    */
  205.         /*    or if any key is clicked.                */
  206.         /*    We also dispatch AppleEvents.            */
  207.     while (!gFinished) {
  208.         gotEvent = WaitNextEvent(everyEvent, &event, 0xFFFFFFFF, NULL);
  209.         if (IsDialogEvent(&event))
  210.             DialogSelect(&event, &theDialog, &itemHit);
  211.         if (gotEvent) 
  212.             switch (event.what) {
  213.                 case mouseDown :
  214.                     pt = event.where;
  215.                     GetPort (&oldPort);
  216.                     SetPort (gDialog);
  217.                     GlobalToLocal (&pt);
  218.                     if (PtInRect (pt, &((GrafPtr)gDialog)->portRect))
  219.                         gFinished = true;
  220.                     SetPort (oldPort);
  221.                     break;
  222.                 case keyDown :
  223.                     gFinished = true;
  224.                     break;
  225.                 case kHighLevelEvent :
  226.                     AEProcessAppleEvent(&event);
  227.                     break;
  228.                 default :
  229.                     break;
  230.             }
  231.     }
  232. }
  233.  
  234. /*****************************************************************************/
  235.         
  236. void CleanupStuff ()
  237. {
  238.     CleanupSpeechRecognitionStuff ();
  239.     
  240.     if (gDialog)
  241.         DisposeDialog (gDialog);
  242. }
  243.  
  244. /*****************************************************************************/
  245.  
  246. void CleanupSpeechRecognitionStuff ()
  247. {
  248.     OSErr status;
  249.     status = SRStopListening (gRecognizer);    /* stop processing incoming sound */
  250.     status = SRReleaseObject (gRecognizer);    /* balance SRNewRecognizer call */
  251.     status = SRCloseRecognitionSystem (gSystem);    /* balance SROpenRecognitionSystem call */
  252. }
  253.  
  254. /*****************************************************************************/
  255.  
  256. /* Here we build a language model to tell the recognizer what it should listen
  257.     for.  Of course, these strings should never be hard-coded into any app, but
  258.     we're doing it here so that under Think you don't need to provide any
  259.     resources.
  260. */
  261.  
  262. OSErr MakeALanguageModel (LanguageModel *model)
  263. {
  264.     OSErr            status;
  265.     LanguageModel    newModel;
  266.     const char        *lmName = "<Sample LM>";
  267.     const char        *phraseStrings[] = {
  268.                         "Hi",
  269.                         "Goodbye",
  270.                         "What time is it",
  271.                         "What day is it",
  272.                         0
  273.                     };
  274.     const char        **phraseStr = phraseStrings;
  275.     
  276.     
  277.         /*    make a simple language model (LM) */
  278.     status = SRNewLanguageModel (gSystem, &newModel, lmName, strlen (lmName));
  279.         
  280.         /*    add each phrase to LM */
  281.     if (!status) {
  282.         while (!status && *phraseStr) {
  283.             status = SRAddText (newModel, *phraseStr, strlen (*phraseStr), 0);
  284.             *phraseStr++;
  285.         }
  286.             
  287.             /*    release newly created LM if an error occured while adding phrases */
  288.         if (status)
  289.             SRReleaseObject (newModel);
  290.     }
  291.     
  292.         /*    return new LM */
  293.     if (!status)
  294.         *model = newModel;
  295.  
  296.     return status;
  297. }
  298.  
  299. /*****************************************************************************/
  300.  
  301. /* Here's an AppleEvent handler for handling the kAESpeechDone event of the
  302.     kAESpeechSuite -- i.e. the event indicating a recognition attempt was made.
  303.     The keySpeechStatus parameter gives the status of the recognition.  If it
  304.     is noErr, then the keySpeechResult parameter gives a RecognitionResult with the
  305.     various representations of the words the user spoke.
  306. */
  307.  
  308. pascal OSErr HandleSpeechDoneAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon)
  309. {
  310. #pragma unused (reply, refcon)
  311.     long                actualSize;
  312.     DescType            actualType;
  313.     OSErr                status = 0, recStatus = 0;
  314.     RecognitionResult    recResult;
  315.     Str255                str;
  316.     Size                len;
  317.     
  318.         /* Get status */
  319.     status = AEGetParamPtr(theAEevt,keySpeechStatus,typeInteger,
  320.                     &actualType, (Ptr)&recStatus, sizeof(status), &actualSize);
  321.  
  322.         /* Get result */
  323.     if (!status && !recStatus)
  324.         status = AEGetParamPtr(theAEevt,keySpeechResult,
  325.                     typeSpeechResult, &actualType, (Ptr)&recResult,
  326.                     sizeof(RecognitionResult), &actualSize);
  327.                     
  328.         /* Get text of words in result.
  329.             Could also get actual phrase, path, or LM objects using other
  330.             format property selectors. If we did that, we'd also want to
  331.             release those objects when we were done using them here.*/
  332.     if (!status) {
  333.         len = 255;
  334.         status = SRGetProperty (recResult, kTEXTFormat, str+1, &len);
  335.         if (!status) {
  336.             str[0] = len;
  337.                 
  338.                 // Release RecognitionResult since we are done with it!!! 
  339.                 //    The toolbox has given us a reference to this object, and
  340.                 //    assumes we are still using it until we call SRReleaseObject
  341.                 //    with it.
  342.             SRReleaseObject (recResult);
  343.         }
  344.     }
  345.     
  346.     if (!status)
  347.         DisplayString (str);
  348.     else
  349.         DisplayString ("\pRecognition error");
  350.  
  351.     return status;
  352. }
  353.  
  354. /*****************************************************************************/
  355.  
  356. void DisplayString (Str255 str)
  357. {
  358.     GrafPtr    oldPort;
  359.     Rect    theRect;
  360.     
  361.     GetPort (&oldPort);
  362.     SetPort (gDialog);
  363.     theRect = ((GrafPtr)gDialog)->portRect;
  364.     theRect.bottom = theRect.bottom-30;
  365.     EraseRect(&theRect);
  366.     TextSize (12);
  367.     MoveTo (40,30);
  368.     DrawString (str);
  369.     SetPort (oldPort);
  370. }
  371.  
  372. /*****************************************************************************/
  373.  
  374.  
  375.